namespace eval ttk::timebox { }

 proc ttk::timebox::Spin {win format action} {
    ttk::timebox::validate_time $win $format {} [$win get] [$win index insert] $action
 }

 proc ttk::timebox::validate_time {win format edit current index action} {
    # Make the action string a little bit more palatable.
     if {$action in {-1 0 1}} {
         set action [dict get {-1 forced 0 delete 1 insert} $action]
     }

     # Forced validation always succeeds.
     if {$action eq "forced"} {
         return true
     }

     # Make the cursor retreat past separator characters.
     if {$index % 3 == 2} {
         incr index -1
     }

     # Determine how many characters are being edited.
     set len [string length $edit]
     set end [expr {$index + $len - 1}]
     set tot [string length $current]

     # Create the format definition lookup table.
     set fmtdef {
         p {place 43200 radix  2} H {place 3600 radix 24} h {place 3600 radix 12}
         m {place    60 radix 60} s {place    1 radix 60}
     }

     # If the entire text is selected, and if using the spinners, advance to the
     # least significant field.
     if {$action in {up down} && [$win selection present]
      && [$win index sel.first] == 0 && [$win index sel.last] == $tot} {
         # Round the index down to a multiple of three.
         set index [expr {$tot / 3 * 3}]

         # If the last field is AM/PM, retreat one field.
         if {[string index $format end] eq "p"} {
             incr index -3
         }
     }

     # Determine the format code of the sub-field being edited.
     set field [string index $format [expr {$index / 3}]]

     # Before doing anything complex, do simple character-based validation.
     if {$action eq "insert" && ($field eq "p"
           ? ($edit ni {a A p P} || $index % 3 != 0)
           : ($edit ni {0 1 2 3 4 5 6 7 8 9}))} {
         return false
     }

     # Figure out the new text after the edit.
     switch -- $action {
     delete {
         set new [string replace $current $index $end [string repeat 0 $len]]
         $win icursor $index
     } insert {
         set new [string replace $current $index $end $edit]
     } default {
         set new $current
     }}

     # Split the data into fields.  It's not safe to use [split] because the
     # colon and space may have just been overwritten.
     set split [list]
     for {set i 0} {$i < [string length $format]} {incr i} {
         lappend split [string range $new [expr {$i * 3}] [expr {$i * 3 + 1}]]
     }

     # Convert to time in seconds since midnight.
     set time 0
     foreach fmt [split $format ""] val $split {
         # Convert the time component to an integer.
         if {$fmt eq "p"} {
             set val [expr {[string index $val 0] in {p P} ? 1 : 0}]
         } elseif {$fmt eq "h" && $val == 12} {
             set val 0
         } else {
             scan $val %d val
         }

         # Forbid out-of-range values.
         if {$val >= [dict get $fmtdef $fmt radix]} {
             return false
         }

         # Add the time component to the seconds accumulator.
         incr time [expr {$val * [dict get $fmtdef $fmt place]}]
     }

     # Handle incrementing and decrementing via the spinner buttons.
     if {$action in {up down}} {
         # Adjust the time according to which field is currently selected.
         incr time [expr {
             ($action eq "down" ? -1 : 1) * [dict get $fmtdef $field place]
         }]

         # Highlight (select) the current field.
         focus $win
         $win selection range [expr {$index / 3 * 3}] [expr {$index / 3 * 3 + 2}]
         $win icursor [expr {$index / 3 * 3 + 2}]
     }

     # Reassemble the time string to include the above changes.
     set new ""
     foreach fmt [split $format ""] {
         # Get the numeric value of this field.
         set val [expr {$time / [dict get $fmtdef $fmt place]
                              % [dict get $fmtdef $fmt radix]}]

         # Add the string-formatted version of this field to the result.
         if {$fmt eq "p"} {
             append new " [lindex {AM PM} $val]"
         } elseif {$fmt eq "h" && $val == 0} {
             append new :12
         } else {
             append new :[format %02d $val]
         }
     }
     set new [string range $new 1 end]

     # Write the new time string to the widget.
     $win set $new

     # When using insert mode, advance the cursor past the separator character.
     if {$action eq "insert"} {
         set cursor [expr {$index + 1}]
         if {$field eq "p" && $cursor % 3 == 1} {
             incr cursor 2
         } elseif {$cursor % 3 == 2} {
             incr cursor
         }
         $win selection clear
         $win icursor $cursor
     }

     # Don't allow Tk to set the widget value; it's already done.
     return false
 }

 proc ttk::timebox {win var format args} {
     # Only allow a limited range of format specifiers.
     set valid {ms hm hmp hms hmsp Hm Hms}
     if {$format ni $valid} {
         error "unsupported format \"$format\": must be [join $valid ", "]"
     }

     # Set an initial time value.
	 upvar 1 $var textvar
	 # set textvar ""
     # foreach fmt [split $format ""] {
         # if {$fmt eq "p"} {
             # append textvar " AM"
         # } elseif {$fmt eq "h"} {
             # append textvar ":12"
         # } else {
             # append textvar ":00"
         # }
     # }
     # set textvar [string range $textvar 1 end]

     # Create the spinbox widget.
     ttk::copyBindings TSpinbox TTimebox_$format

     bind TTimebox_$format <<Increment>>    [list ttk::timebox::Spin %W $format up]
     bind TTimebox_$format <<Decrement>>    [list ttk::timebox::Spin %W $format down]

     ttk::spinbox $win {*}$args -class TTimebox_$format -textvariable $var -validate key\
             -validatecommand [list ttk::timebox::validate_time %W $format %S %s %i %d]

     # Position the insertion cursor to the least significant field.
     if {[string index $format end] eq "p"} {
         $win icursor [expr {[string length $textvar] - 4}]
     } else {
         $win icursor end
     }

     # Return the widget path to the caller.
     return $win
 }